package com.smsc.headend.task.engine.handler.impl.whitelist;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.smsc.headend.common.enums.errorcode.TaskHandlerErrorCode;
import com.smsc.headend.module.asset.dto.MeterDTO;
import com.smsc.headend.module.asset.entity.Meter;
import com.smsc.headend.module.protocol.DeviceData;
import com.smsc.headend.module.protocol.cosem.bo.CosemData;
import com.smsc.headend.module.task.dto.AtomicTask;
import com.smsc.headend.module.task.dto.Task;
import com.smsc.headend.task.engine.dao.TaskDAO;
import com.smsc.headend.task.engine.exception.UDISTaskHandlerException;
import com.smsc.headend.task.engine.handler.TaskHandler;
import com.smsc.headend.task.engine.service.FeignAssetManagementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;


@Slf4j
public class ReadMeterListHandler implements TaskHandler {
    @Autowired
    TaskDAO taskDAO;
    @Autowired
    FeignAssetManagementService assetManagementService;

    @Override
    public int handle(Task task, AtomicTask atomicTask, DeviceData deviceData, String actionResult) throws UDISTaskHandlerException {
        if (!(deviceData instanceof CosemData)) {
            throw new UDISTaskHandlerException(TaskHandlerErrorCode.DEVICE_DATA_TYPE_NOT_SUPPORT.toString());
        }

        CosemData cosemData = (CosemData) deviceData;
        List<CosemData> children = cosemData.getChild();
        Map<String, String> serialNums = MapUtil.newHashMap();
        if (!CollectionUtils.isEmpty(children)) {
            for (CosemData child : children) {
                List<CosemData> children1 = child.getChild();
                if (children1.size() == 13) {
                    int i = 0;
                    StringBuilder meterInfoStr = new StringBuilder();
                    meterInfoStr.append("DatacollectorId: ").append(children1.get(i++).getValue()).append(";");
                    String meterId = children1.get(i++).getValue();
                    meterInfoStr.append("MeterId: ").append(meterId).append(";");
                    String protocolType = children1.get(i++).getValue();
                    String protocol = "";
                    if(StrUtil.isNotEmpty(protocolType)) {
                        Integer pt = Convert.toInt(protocolType);
                        if (pt == 0) {
                            protocol = "DLMS/COSEM";
                        } else if (pt == 1) {
                            protocol = "GB645";
                        }
                    }
                    meterInfoStr.append("ProtocolType: ").append(protocol).append(";");
                    String commonTypeStr = children1.get(i++).getValue();
                    String commonType = "";
                    if(StrUtil.isNotEmpty(commonTypeStr)) {
                        Integer ct = Convert.toInt(commonTypeStr);
                        if (ct == 0) {
                            commonType = "CommTypeUnknown";
                        } else if (ct == 1) {
                            commonType = "CommTypeRf/PLC";
                        } else if (ct == 2) {
                            commonType = "CommTypeInternallyRf/PLC";
                        } else if (ct == 3) {
                            commonType = "CommType485";
                        } else if (ct == 4) {
                            commonType = "CommTypeInner";
                        }
                    }
                    meterInfoStr.append("CommType: ").append(commonType).append(";");
                    meterInfoStr.append("Initiate control word: ").append(children1.get(i++).getValue()).append(";");
                    meterInfoStr.append("ClientId: ").append(children1.get(i++).getValue()).append(";");
                    meterInfoStr.append("SecurityControl: ").append(children1.get(i++).getValue()).append(";");
                    meterInfoStr.append("ContextId: ").append(children1.get(i++).getValue()).append(";");
                    meterInfoStr.append("SecurityKey: ").append(children1.get(i++).getValue()).append(";");
                    meterInfoStr.append("MechanismId: ").append(children1.get(i++).getValue()).append(";");
                    meterInfoStr.append("MechanismKey: ").append(children1.get(i++).getValue()).append(";");
                    meterInfoStr.append("DedKeyEnable: ").append(children1.get(i++).getValue()).append(";");
                    meterInfoStr.append("PSK: ").append(children1.get(i++).getValue()).append(";");
                    serialNums.put(meterId, meterInfoStr.toString());
                    Meter meter = assetManagementService.getMeter(meterId);
                    if (meter != null) {
                        updateMeterMountStatus(meter);
                    }
                } else {
                    log.debug("data format error");
                }
            }
        }

        //白名单以及TerminalId
        taskDAO.addTaskData(task.getTaskNo(), atomicTask.getAtomicTaskNo(), String.valueOf(task.getComId()), serialNums, Long.valueOf(1 * 60 * 60), true);
        return 1;
    }

    @Override
    public int handleFailure(Task task, AtomicTask atomicTask, String message) {
        taskDAO.addTaskData(task.getTaskNo(), atomicTask.getAtomicTaskNo(), "message", message, 3600l, false);
        return -1;
    }

    private void updateMeterMountStatus(Meter meter) {
        MeterDTO meterDTO = new MeterDTO();
        meterDTO.setMeterId(meter.getMeterId());
        boolean isNeedUpdate = false;
        if (meter.getChannelType().equals("PLC") && meter.getMountStatus() != null && meter.getMountStatus() != Meter.MeterMountStatus.Mounted.getCode()) {
            // 更新注挂接状态
            meterDTO.setMountStatus(Meter.MeterMountStatus.Mounted.getCode());
            isNeedUpdate = true;
            log.debug("update meter mount status {}", meter.getMeterId());
        }
        if (isNeedUpdate) {
            assetManagementService.updateMeterStatus(meterDTO);
        }
    }
}
